﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Xml;

namespace OpenST
{
    /// <summary>
    /// This class takes a Composition and handles all the drawing of it. Zooming and such is handled here.
    /// </summary>
    class CompositionRenderer
    {



        // The size of the squares at zoom level 1.0;
        public const int BaseTileSize = 16;

        public Composition composition;
        private Game game;

        public float Zoom = 1f;
        public Vector2 Origin;

        private Color[] NoteColors;
        private Color[] NoteShades;
        private Texture2D BugStartTile;

        private bool isDragging= false;
        private Vector2 draggingOffset;

        private SpriteBatch spritebatch;



        public CompositionRenderer(Game thegame)
        {
            game = thegame;
            Origin = Vector2.Zero;
        }

        public void SetComposition(Composition compo)
        {
            composition = compo;
        }

        public void LoadContent(ContentManager content)
        {
            DataFormats.NoteColors nc = content.Load<DataFormats.NoteColors>("NoteColors");       
            NoteColors = nc.colors;
            NoteShades = nc.shades;

            BugStartTile = content.Load<Texture2D>("Tiles/TileStart");

            spritebatch = new SpriteBatch(game.GraphicsDevice);
        }

        public void ZoomIn()
        {
            Zoom += 0.2f;
            Zoom = MathHelper.Clamp(Zoom, 0.1f, 4.0f);
        }

        public void ZoomOut()
        {
            Zoom -= 0.2f;
            Zoom = MathHelper.Clamp(Zoom, 0.1f, 4.0f);
        }

        public void Update(GameTime gametime)
        {
            // No matter what goes on, Right click dragging is always active
            MouseState mousstate = Mouse.GetState();
            Vector2 mousepos = new Vector2(mousstate.X, mousstate.Y);

            if (mousstate.RightButton == ButtonState.Pressed && isDragging == false)
            {
                isDragging = true;
                draggingOffset = mousepos - Origin;
            }

            if (mousstate.RightButton == ButtonState.Released && isDragging == true)
            {
                isDragging = false;
            }

            if (isDragging)
            {
                Origin = mousepos - draggingOffset;
            }
        }

        public void Draw(GameTime gametime)
        {
            spritebatch.Begin();

            // Draw The Tiles...
            // Determine Start and end of what needs to be drawn...
            int StartX;
            int StartY;
            int Width;
            int Height;

            StartX = (int)(-Origin.X / (BaseTileSize * Zoom));
            StartY = (int)(-Origin.Y / (BaseTileSize * Zoom));
            StartX = (int)MathHelper.Clamp(StartX, 0, Composition.CompositionMaxSizeX);
            StartY = (int)MathHelper.Clamp(StartY, 0, Composition.CompositionMaxSizeY);

            Width = game.GraphicsDevice.Viewport.Width / (int)Math.Floor(BaseTileSize * Zoom);
            Height = game.GraphicsDevice.Viewport.Height / (int)Math.Floor(BaseTileSize * Zoom);

            int endx = (int)MathHelper.Clamp(StartX + (Width + 5), 0, Composition.CompositionMaxSizeX);
            int endY = (int)MathHelper.Clamp(StartY + (Height + 5), 0, Composition.CompositionMaxSizeY);

            // TODO: FIX ZOOM BUG (+5 above is to hide the bug)

            for (int x = StartX; x < endx; x++)
            {
                for (int y = StartY; y < endY; y++)
                {
                    //  && composition.Tiles[x,y].GetType().ToString() != "OpenST.Tiles.BlankTile"
                    if (composition.Tiles[x,y] != null)
                    {
                        if (composition.Tiles[x, y].Sprite != null)
                        {

                            Vector2 TileScreenPos = new Vector2(((int)(BaseTileSize * Zoom) * x) + (int)Origin.X, ((int)(BaseTileSize * Zoom) * y) + (int)Origin.Y);
                            Vector2 TileSize = new Vector2((int)(BaseTileSize * Zoom), (int)(BaseTileSize * Zoom));
                            int notecol = composition.Tiles[x, y].NoteNumber;
                                    bool color = composition.Tiles[x, y].color;

                                    // IS this a greyscale tile?
                                    if (color == true)
                                    {
                                        spritebatch.Draw(composition.Tiles[x, y].Sprite, new Rectangle(
                                            (int)TileScreenPos.X,
                                            (int)TileScreenPos.Y,
                                            (int)TileSize.X,
                                            (int)TileSize.Y), NoteColors[notecol]);
                                    }
                                    else
                                    {
                                        spritebatch.Draw(composition.Tiles[x, y].Sprite, new Rectangle(
                                            (int)TileScreenPos.X,
                                            (int)TileScreenPos.Y,
                                            (int)TileSize.X,
                                            (int)TileSize.Y), NoteShades[notecol]);
                                    }

                            
                        } // Tile sprite check
                    } // Tile Check
                    
                } // Y
            } // X
            

            // Draw bugs and start positions...
            foreach (Bug b in composition.Bugs)
            {
                // Start pos

                Vector2 TileScreenPos = new Vector2(((int)(BaseTileSize * Zoom) * b.StartX) + (int)Origin.X, ((int)(BaseTileSize * Zoom) * b.StartY) + (int)Origin.Y);
                Vector2 TileSize = new Vector2((int)(BaseTileSize * Zoom), (int)(BaseTileSize * Zoom));
                spritebatch.Draw(BugStartTile, new Rectangle(
                    (int)TileScreenPos.X,
                    (int)TileScreenPos.Y,
                    (int)TileSize.X,
                    (int)TileSize.Y), Color.White);

                // Bug

                Vector2 bugscreenpos = new Vector2((int)(BaseTileSize * Zoom) * b.PositionX, (int)(BaseTileSize * Zoom) * b.PositionY);
                Vector2 bugtargetscreenpos;

                switch (b.CurrentDirection)
                {
                    case Bug.Direction.Right:
                        bugtargetscreenpos = new Vector2((int)(BaseTileSize * Zoom) * (b.PositionX + 1), (int)(BaseTileSize * Zoom) * b.PositionY);
                        break;
                    case Bug.Direction.Left:
                        bugtargetscreenpos = new Vector2((int)(BaseTileSize * Zoom) * (b.PositionX - 1), (int)(BaseTileSize * Zoom) * b.PositionY);
                        break;
                    case Bug.Direction.Down:
                        bugtargetscreenpos = new Vector2((int)(BaseTileSize * Zoom) * b.PositionX, (int)(BaseTileSize * Zoom) * (b.PositionY + 1));
                        break;
                    case Bug.Direction.Up:
                        bugtargetscreenpos = new Vector2((int)(BaseTileSize * Zoom) * b.PositionX, (int)(BaseTileSize * Zoom) * (b.PositionY - 1));
                        break;
                    default:
                        bugtargetscreenpos = new Vector2(0,0); // Just to stop "Use of possibly unasigned blah"
                        break;

                }

                
                // Lerp between tiles is in this mess
                spritebatch.Draw(b.BugSprite, new Rectangle(
                                (int)MathHelper.Lerp(bugscreenpos.X,bugtargetscreenpos.X,b.ProgressToNextTile) + (int)Origin.X,
                                (int)MathHelper.Lerp(bugscreenpos.Y, bugtargetscreenpos.Y, b.ProgressToNextTile) + (int)Origin.Y,
                                (int)(BaseTileSize * Zoom),
                                (int)(BaseTileSize * Zoom)), Color.White);
                    
            }

            spritebatch.End();
        }
    }
}
